/**
 @file ctc_acl_cli.c

 @date 2020-06-19

 @version v0.0

---file comments----
*/

/****************************************************************
 *
 * Header Files
 *
 ***************************************************************/
#include "sal.h"
#include "ctc_cli.h"
#include "ctc_cli_common.h"
#include "api/include/ctcs_api.h"
#include "ctc_common.h"
#include "ctc_diag_cli.h"

#define CTC_ASW_ACL_UDF_FIELD_NUM  4

#define CTC_CLI_ACL_ENTRY_TYPE_STR \
"mac-entry|     \
ipv4-entry|     \
ipv6-entry |    \
ipv4-ext-entry| \
mac-udf-entry|  \
mac-ipv4-entry| \
ipv6-ext-entry| \
mac-ipv6-entry| \
udf-entry"

#define CTC_CLI_ACL_ENTRY_TYPE_DESC \
    "mac entry", "ipv4 entry","ipv6 entry", "ipv4 extend entry", \
    "mac udf entry", "mac ipv4 entry", "ipv6 extend entry", "mac ipv6 entry", "udf entry"

#define CTC_CLI_ACL_KEY_FIELD_STR \
" l2-type (eth-v2 | eth-sap | eth-snap | ) (MASK|) \
| l3-type (ipv4 | ipv6 |) (MASK|)\
| l4-type (tcp | udp | icmp | igmp |) (MASK|) \
| field-port (port-bitmap PORT_BITMAP) \
| mac-sa (VALUE (MASK|)|) \
| mac-da (VALUE (MASK|)|) \
| stag-valid (VALUE (MASK|)|) \
| svlan-id (VALUE (MASK|)|) \
| stag-cos (VALUE (MASK|)|) \
| stag-cfi (VALUE (MASK|)|) \
| ctag-valid (VALUE (MASK|)|) \
| cvlan-id (VALUE (MASK|)|) \
| ctag-cos (VALUE (MASK|)|) \
| ctag-cfi (VALUE (MASK|)|) \
| ether-type (VALUE (MASK|)|) \
| ip-sa (VALUE (MASK|)|) \
| ip-da (VALUE (MASK|)|) \
| ipv6-sa (VALUE (MASK|)|) \
| ipv6-da (VALUE (MASK|)|) \
| ip-protocol (VALUE (MASK|)|) \
| ip-frag (VALUE (MASK|)|) \
| ip-options (VALUE (MASK|)|) \
| ip-pkt-len-range (VALUE (MASK|)|) \
| l4-dst-port (VALUE (MASK|)|) \
| l4-src-port (VALUE (MASK|)|) \
| l4-src-port-range (VALUE (MASK|)|) \
| l4-dst-port-range (VALUE (MASK|)|) \
| tcp-flags (VALUE (MASK|)|) \
| icmp-code (VALUE (MASK|)|) \
| icmp-type (VALUE (MASK|)|) \
| udf udf-id UDF_ID {udf-data VALUE MASK| } \
| dscp DSCP (VALUE (MASK|)|)\
"

#define CTC_CLI_ACL_KEY_FIELD_DESC \
"layer 2 type  ", "eth-v2", "eth-sap", "eth-snap", "mask",\
"layer 3 type  ", "ipv4 pkt", "ipv6 pkt","mask",\
"layer 4 type", "tcp" , "udp" , "icmp" , "igmp","mask",\
"port-type","port bitmap","port bitmap value",\
"source mac address ","value", "mask",\
"destination mac address ", "value", "mask",\
"s-vlan exist ", "value", "mask",\
"s-vlan id ", "value", "mask",\
"stag cos ", "value", "mask",\
"stag cfi ", "value", "mask",\
"c-vlan exist ", "value", "mask",\
"c-vlan id ", "value", "mask",\
"ctag cos ", "value", "mask",\
"ctag cfi ", "value", "mask",\
"ether type ", "value", "mask",\
"source ipv4 address ", "value", "mask",\
"destination ipv4 address ", "value", "mask",\
"source ipv6 address ", "value", "mask",\
"destination ipv6 address ", "value", "mask",\
"ip protocol ", "value", "mask",\
"ip fragment information ", "value", "mask",\
"ip options ", "value", "mask",\
"ip packet length range ", "value", "mask",\
"layer 4 dest port ", "value", "mask",\
"layer 4 src port ", "value", "mask",\
"layer 4 src port range ", "value", "mask",\
"layer 4 dest port range ", "value", "mask",\
"tcp flags ", "value", "mask",\
"icmp code", "value", "mask",\
"icmp type", "value", "mask",\
"udf","udf id","udf id value","udf data","value","mask", \
"ip-dscp", "dscp value" ,"value","mask"


#define CTC_CLI_ACL_ADD_FIELD_ACTION_STR \
   "| deny-learning \
    | stats STATS-ID \
    | random-log \
    | dscp DSCP \
    | micro-flow-policer POLICER-ID \
    | redirect-port PORT_BITMAP LAG_BITMAP \
    | discard \
    | vlan-edit (scos-sl TAG_SL {new-scos COS | new-scfi CFI |}|) \
    | copy-to-cpu mode MODE (cpu-reason-id REASON|)  \
    | swap-mac \
    | qos-map domain DOMAIN (trust-dscp | trust-scos )"


#define CTC_CLI_ACL_ADD_FIELD_ACTION_DESC \
    "Deny learning ", \
    "Packet statistics ","Stats id" , \
    "Random log to cpu ", \
    "Dscp ","Dscp" ,\
    "Micor flow policer ","Micro policer id" , \
    "Redirect packet to single port ", "port bitmap 0~28","linkagg group bitmap 0~4", \
    "Discard", \
    "Vlan edit", "Scos select", CTC_CLI_TAG_SL_DESC,"New stag cos", CTC_CLI_COS_RANGE_DESC,"New stag cfi", CTC_CLI_CFI_RANGE_DESC, \
    "Copy to cpu","Mode","Value: 0 -not cover 1 -cover","cpu reason id","value", \
    "Swap mac address",\
    "Qos table map","doamin id","Domain value", "maped by dscp", "maped by scos"


#define CTC_CLI_ACL_ADD_FIELD_ACTION_SET(act_field, arg) \
do{\
    index = CTC_CLI_GET_ARGC_INDEX("deny-learning");\
    if (0xFF != index) \
    {\
        act_field->type = CTC_ACL_FIELD_ACTION_DENY_LEARNING;\
        act_field->data0 = 1;\
        arg;\
    }\
    index = CTC_CLI_GET_ARGC_INDEX("random-log");\
    if (0xFF != index) \
    {\
        act_field->type = CTC_ACL_FIELD_ACTION_RANDOM_LOG;\
        arg;\
    }\
    index = CTC_CLI_GET_ARGC_INDEX("discard");\
    if (0xFF != index) \
    {\
        act_field->type = CTC_ACL_FIELD_ACTION_DISCARD;\
        arg;\
    }\
    index = CTC_CLI_GET_ARGC_INDEX("copy-to-cpu");\
    if (0xFF != index) \
    {\
        act_field->type = CTC_ACL_FIELD_ACTION_CP_TO_CPU;\
        index = CTC_CLI_GET_ARGC_INDEX("mode");\
        if (0xFF != index) \
        {\
            CTC_CLI_GET_UINT8("mode",cp_to_cpu.mode, argv[index + 1]);\
        }\
        index = CTC_CLI_GET_ARGC_INDEX("cpu-reason-id");\
        if (0xFF != index) \
        {\
            CTC_CLI_GET_UINT16("cpu-reason-id",cp_to_cpu.cpu_reason_id, argv[index + 1]);\
        }\
        act_field->ext_data = &cp_to_cpu;\
        arg;\
    }\
    index = CTC_CLI_GET_ARGC_INDEX("redirect-port");\
    if (0xFF != index) \
    {\
        act_field->type = CTC_ACL_FIELD_ACTION_REDIRECT_PORT;\
        CTC_CLI_GET_UINT32("port bitmap", act_field->data0, argv[index + 1]);\
        CTC_CLI_GET_UINT32("linkagg bitmap", act_field->data1, argv[index + 2]);\
        arg;\
    }\
    index = CTC_CLI_GET_ARGC_INDEX("micro-flow-policer");\
    if (0xFF != index) \
    {\
        act_field->type = CTC_ACL_FIELD_ACTION_MICRO_FLOW_POLICER;\
        CTC_CLI_GET_UINT32("value", act_field->data0, argv[index + 1]);\
        arg;\
    }\
    index = CTC_CLI_GET_ARGC_INDEX("stats");\
    if (0xFF != index) \
    {\
        act_field->type = CTC_ACL_FIELD_ACTION_STATS;\
        CTC_CLI_GET_UINT32("value", act_field->data0, argv[index + 1]);\
        arg;\
    }\
    index = CTC_CLI_GET_ARGC_INDEX("vlan-edit");                                            \
    if (INDEX_VALID(index))                                                                  \
    {                                                                                       \
        index = CTC_CLI_GET_ARGC_INDEX("scos-sl");                                              \
        if (INDEX_VALID(index))                                                                  \
        {                                                                                       \
            CTC_CLI_GET_UINT8("scos-sl", vlan_edit.scos_sl, argv[index + 1]);         \
        }                                                                                       \
        index = CTC_CLI_GET_ARGC_INDEX("new-scos");                                              \
        if (INDEX_VALID(index))                                                                  \
        {                                                                                       \
            CTC_CLI_GET_UINT8("new-scos", vlan_edit.scos_new, argv[index + 1]);         \
        }                                                                                       \
        index = CTC_CLI_GET_ARGC_INDEX("new-scfi");                                              \
        if (INDEX_VALID(index))                                                                  \
        {                                                                                       \
            CTC_CLI_GET_UINT8("new-scfi", vlan_edit.scfi_new, argv[index + 1]);         \
        }                                                                                       \
        act_field->type = CTC_ACL_FIELD_ACTION_VLAN_EDIT;\
        act_field->ext_data = &vlan_edit;\
        arg;  \
    }\
    index = CTC_CLI_GET_ARGC_INDEX("dscp");\
    if (0xFF != index) \
    {\
        act_field->type = CTC_ACL_FIELD_ACTION_DSCP;\
        CTC_CLI_GET_UINT32("dscp", act_field->data0, argv[index + 1]);\
        arg;\
    }\
    index = CTC_CLI_GET_ARGC_INDEX("swap-mac");\
    if (0xFF != index) \
    {\
        act_field->type = CTC_ACL_FIELD_ACTION_SWAP_MAC;\
        arg;\
    }\
    index = CTC_CLI_GET_ARGC_INDEX("qos-map");\
    if (0xFF != index) \
    {\
        act_field->type = CTC_ACL_FIELD_ACTION_QOS_TABLE_MAP;\
        act_field->ext_data = &qos_map;\
        CTC_CLI_GET_UINT32("map_id", qos_map.table_map_id, argv[index + 2]);\
        index = CTC_CLI_GET_ARGC_INDEX("trust-dscp");\
        if (0xFF != index) \
        {\
            qos_map.table_map_type = 1;\
        }\
        arg;\
    }\
}while(0)


#define CTC_CLI_ACL_KEY_TYPE_SET \
do{\
    index = CTC_CLI_GET_ARGC_INDEX("mac-entry");\
    if (0xFF != index) \
    {\
        acl_entry.key_type = CTC_ACL_KEY_MAC;\
        break;\
    }\
    index = CTC_CLI_GET_ARGC_INDEX("ipv4-entry");\
    if (0xFF != index) \
    {\
        acl_entry.key_type = CTC_ACL_KEY_IPV4;\
        break;\
    }\
    index = CTC_CLI_GET_ARGC_INDEX("ipv6-entry");\
    if (0xFF != index) \
    {\
        acl_entry.key_type = CTC_ACL_KEY_IPV6;\
        break;\
    }\
    index = CTC_CLI_GET_ARGC_INDEX("ipv4-ext-entry");\
    if (0xFF != index) \
    {\
        acl_entry.key_type = CTC_ACL_KEY_IPV4_EXT;\
        break;\
    }\
    index = CTC_CLI_GET_ARGC_INDEX("mac-udf-entry");\
    if (0xFF != index) \
    {\
        acl_entry.key_type = CTC_ACL_KEY_MAC_EXT;\
        break;\
    }\
    index = CTC_CLI_GET_ARGC_INDEX("mac-ipv4-entry");\
    if (0xFF != index) \
    {\
        acl_entry.key_type = CTC_ACL_KEY_MAC_IPV4;\
        break;\
    }\
    index = CTC_CLI_GET_ARGC_INDEX("ipv6-ext-entry");\
    if (0xFF != index) \
    {\
        acl_entry.key_type = CTC_ACL_KEY_IPV6_EXT;\
        break;\
    }\
    index = CTC_CLI_GET_ARGC_INDEX("mac-ipv6-entry");\
    if (0xFF != index) \
    {\
        acl_entry.key_type = CTC_ACL_KEY_MAC_IPV6;\
        break;\
    }\
    index = CTC_CLI_GET_ARGC_INDEX("udf-entry");\
    if (0xFF != index) \
    {\
        acl_entry.key_type = CTC_ACL_KEY_UDF;\
        break;\
    }\
}while(0)


#define CTC_CLI_ACL_KEY_FIELD_SET(key_field, arg, start)\
    do{\
        index = CTC_CLI_GET_ARGC_INDEX("l2-type");\
        if (0xFF != index) \
        {\
            key_field->type = CTC_FIELD_KEY_L2_TYPE;\
            if(is_add)\
            {\
                key_field->mask = 0xf;\
                if(0xFF != CTC_CLI_GET_ARGC_INDEX("eth-v2"))\
                    key_field->data = CTC_PARSER_L2_TYPE_ETH_V2;\
                else if(0xFF != CTC_CLI_GET_ARGC_INDEX("eth-sap"))\
                    key_field->data = CTC_PARSER_L2_TYPE_ETH_SAP;\
                else if(0xFF != CTC_CLI_GET_ARGC_INDEX("eth-snap"))\
                    key_field->data = CTC_PARSER_L2_TYPE_ETH_SNAP;\
                if(index+2<argc) CTC_CLI_GET_UINT32("mask", key_field->mask, argv[index + 2]);\
            }\
            arg;\
        }\
        index = CTC_CLI_GET_ARGC_INDEX("l3-type");\
        if (0xFF != index) \
        {\
            key_field->type = CTC_FIELD_KEY_L3_TYPE;\
            if(is_add)\
            {\
                key_field->mask = 0xf;\
                if(0xFF != CTC_CLI_GET_ARGC_INDEX("ipv4"))\
                    key_field->data = CTC_PARSER_L3_TYPE_IPV4;\
                else if(0xFF != CTC_CLI_GET_ARGC_INDEX("ipv6"))\
                    key_field->data = CTC_PARSER_L3_TYPE_IPV6;\
                if(index+2<argc) CTC_CLI_GET_UINT32("mask", key_field->mask, argv[index + 2]);\
            }\
            arg;\
        }\
        index = CTC_CLI_GET_ARGC_INDEX("l4-type");\
        if (0xFF != index) \
        {\
            key_field->type = CTC_FIELD_KEY_L4_TYPE;\
            if(is_add)\
            {\
                key_field->mask = 0xf;\
                if(0xFF != CTC_CLI_GET_ARGC_INDEX("tcp"))\
                    key_field->data = CTC_PARSER_L4_TYPE_TCP;\
                else if(0xFF != CTC_CLI_GET_ARGC_INDEX("udp"))\
                    key_field->data = CTC_PARSER_L4_TYPE_UDP;\
                else if(0xFF != CTC_CLI_GET_ARGC_INDEX("icmp"))\
                    key_field->data = CTC_PARSER_L4_TYPE_ICMP;\
                else if(0xFF != CTC_CLI_GET_ARGC_INDEX("igmp"))\
                    key_field->data = CTC_PARSER_L4_TYPE_IGMP;\
                if(index+2<argc) CTC_CLI_GET_UINT32("mask", key_field->mask, argv[index + 2]);\
            }\
            arg;\
        }\
        index = CTC_CLI_GET_ARGC_INDEX("mac-sa");\
        if (0xFF != index) \
        {\
            key_field->type = CTC_FIELD_KEY_MAC_SA;\
            if(is_add)\
            {\
                CTC_CLI_GET_MAC_ADDRESS("mac-sa", mac_sa_addr, argv[index + 1]);\
                key_field->ext_data = mac_sa_addr; \
                sal_memset(&mac_sa_addr_mask, 0xFF, sizeof(mac_addr_t));\
                if(index+2<argc){\
                CTC_CLI_GET_MAC_ADDRESS("mac-sa-mask", mac_sa_addr_mask, argv[index + 2]);\
                key_field->ext_mask = mac_sa_addr_mask;} \
            }\
            arg;\
        }\
        index = CTC_CLI_GET_ARGC_INDEX("mac-da");\
        if (0xFF != index) \
        {\
            key_field->type = CTC_FIELD_KEY_MAC_DA;\
            if(is_add)\
            {\
                key_field->type = CTC_FIELD_KEY_MAC_DA;\
                CTC_CLI_GET_MAC_ADDRESS("mac-da", mac_da_addr, argv[index + 1]);\
                key_field->ext_data = mac_da_addr; \
                sal_memset(&mac_da_addr_mask, 0xFF, sizeof(mac_addr_t));\
                if(index+2<argc){\
                CTC_CLI_GET_MAC_ADDRESS("mac-da-mask", mac_da_addr_mask, argv[index + 2]);\
                key_field->ext_mask = mac_da_addr_mask;} \
            }\
            arg;\
        }\
        index = CTC_CLI_GET_ARGC_INDEX("stag-valid");\
        if (0xFF != index) \
        {\
            key_field->type = CTC_FIELD_KEY_STAG_VALID;\
            if(is_add)\
            {\
                CTC_CLI_GET_UINT32("value", key_field->data, argv[index + 1]);\
                if(index+2<argc) CTC_CLI_GET_UINT32("mask", key_field->mask, argv[index + 2]);\
            }\
            arg;\
        }\
        index = CTC_CLI_GET_ARGC_INDEX("svlan-id");\
        if (0xFF != index) \
        {\
            key_field->type = CTC_FIELD_KEY_SVLAN_ID;\
            if(is_add)\
            {\
                CTC_CLI_GET_UINT32("value", key_field->data, argv[index + 1]);\
                if (index+2<argc) CTC_CLI_GET_UINT32("mask", key_field->mask, argv[index + 2]); \
            }\
            arg;\
        }\
        index = CTC_CLI_GET_ARGC_INDEX("stag-cos");\
        if (0xFF != index) \
        {\
            key_field->type = CTC_FIELD_KEY_STAG_COS;\
            if(is_add)\
            {\
                CTC_CLI_GET_UINT32("value", key_field->data, argv[index + 1]);\
                if(index+2<argc) CTC_CLI_GET_UINT32("mask", key_field->mask, argv[index + 2]);\
            }\
            arg;\
        }\
        index = CTC_CLI_GET_ARGC_INDEX("stag-cfi");\
        if (0xFF != index) \
        {\
            key_field->type = CTC_FIELD_KEY_STAG_CFI;\
            if(is_add)\
            {\
                CTC_CLI_GET_UINT32("value", key_field->data, argv[index + 1]);\
                if(index+2<argc) CTC_CLI_GET_UINT32("mask", key_field->mask, argv[index + 2]);\
            }\
            arg;\
        }\
        index = CTC_CLI_GET_ARGC_INDEX("ctag-valid");\
        if (0xFF != index) \
        {\
            key_field->type = CTC_FIELD_KEY_CTAG_VALID;\
            if(is_add)\
            {\
                CTC_CLI_GET_UINT32("value", key_field->data, argv[index + 1]);\
                if(index+2<argc) CTC_CLI_GET_UINT32("mask", key_field->mask, argv[index + 2]);\
            }\
            arg;\
        }\
        index = CTC_CLI_GET_ARGC_INDEX("cvlan-id");\
        if (0xFF != index) \
        {\
            key_field->type = CTC_FIELD_KEY_CVLAN_ID;\
            if(is_add)\
            {\
                CTC_CLI_GET_UINT32("value", key_field->data, argv[index + 1]);\
                if(index+2<argc) CTC_CLI_GET_UINT32("mask", key_field->mask, argv[index + 2]);\
            }\
            arg;\
        }\
        index = CTC_CLI_GET_ARGC_INDEX("ctag-cos");\
        if (0xFF != index) \
        {\
            key_field->type = CTC_FIELD_KEY_CTAG_COS;\
            if(is_add)\
            {\
                CTC_CLI_GET_UINT32("value", key_field->data, argv[index + 1]);\
                if(index+2<argc) CTC_CLI_GET_UINT32("mask", key_field->mask, argv[index + 2]);\
            }\
            arg;\
        }\
        index = CTC_CLI_GET_ARGC_INDEX("ctag-cfi");\
        if (0xFF != index) \
        {\
            key_field->type = CTC_FIELD_KEY_CTAG_CFI;\
            if(is_add)\
            {\
                CTC_CLI_GET_UINT32("value", key_field->data, argv[index + 1]);\
                if(index+2<argc) CTC_CLI_GET_UINT32("mask", key_field->mask, argv[index + 2]);\
            }\
            arg;\
        }\
        index = CTC_CLI_GET_ARGC_INDEX("ether-type");\
        if (0xFF != index) \
        {\
            key_field->type = CTC_FIELD_KEY_ETHER_TYPE;\
            if(is_add)\
            {\
                CTC_CLI_GET_UINT32("value", key_field->data, argv[index + 1]);\
                if(index+2<argc) CTC_CLI_GET_UINT32("mask", key_field->mask, argv[index + 2]);\
            }\
            arg;\
        }\
        index = CTC_CLI_GET_ARGC_INDEX("ip-sa");\
        if (0xFF != index) \
        {\
            key_field->type = CTC_FIELD_KEY_IP_SA;\
            if(is_add)\
            {\
                CTC_CLI_GET_IPV4_ADDRESS("ipsa", key_field->data, argv[index + 1]);\
                key_field->mask = 0xFFFFFFFF;\
                if(index+2<argc) CTC_CLI_GET_IPV4_ADDRESS("mask", key_field->mask, argv[index + 2]);\
            }\
            arg;\
        }\
        index = CTC_CLI_GET_ARGC_INDEX("ip-da");\
        if (0xFF != index) \
        {\
            key_field->type = CTC_FIELD_KEY_IP_DA;\
            if(is_add)\
            {\
                CTC_CLI_GET_IPV4_ADDRESS("ipda", key_field->data, argv[index + 1]);\
                key_field->mask = 0xFFFFFFFF;\
                if(index+2<argc) CTC_CLI_GET_IPV4_ADDRESS("mask", key_field->mask, argv[index + 2]);\
            }\
            arg;\
        }\
        index = CTC_CLI_GET_ARGC_INDEX("ipv6-sa");\
        if (0xFF != index) \
        {\
            key_field->type = CTC_FIELD_KEY_IPV6_SA;\
            if(is_add)\
            {\
                CTC_CLI_GET_IPV6_ADDRESS("ip-sa", ipv6_sa_addr, argv[index + 1]);               \
                ipv6_sa_addr[0] = sal_htonl(ipv6_sa_addr[0]);                                 \
                ipv6_sa_addr[1] = sal_htonl(ipv6_sa_addr[1]);                                 \
                ipv6_sa_addr[2] = sal_htonl(ipv6_sa_addr[2]);                                 \
                ipv6_sa_addr[3] = sal_htonl(ipv6_sa_addr[3]);                                 \
                key_field->ext_data = ipv6_sa_addr;    \
                if(index+2<argc)\
                {\
                    if CLI_CLI_STR_EQUAL("HOST", index + 2)                                          \
                    {                                                                             \
                        ipv6_sa_addr_mask[0] = 0xFFFFFFFF;                                            \
                        ipv6_sa_addr_mask[1] = 0xFFFFFFFF;                                            \
                        ipv6_sa_addr_mask[2] = 0xFFFFFFFF;                                            \
                        ipv6_sa_addr_mask[3] = 0xFFFFFFFF;                                            \
                        key_field->ext_mask = ipv6_sa_addr_mask;    \
                    }                                                                             \
                    else                                                                          \
                    {                                                                             \
                        CTC_CLI_GET_IPV6_ADDRESS("ip-sa-mask", ipv6_sa_addr_mask, argv[index + 2]);          \
                        ipv6_sa_addr_mask[0] = sal_htonl(ipv6_sa_addr_mask[0]);                                 \
                        ipv6_sa_addr_mask[1] = sal_htonl(ipv6_sa_addr_mask[1]);                                 \
                        ipv6_sa_addr_mask[2] = sal_htonl(ipv6_sa_addr_mask[2]);                                 \
                        ipv6_sa_addr_mask[3] = sal_htonl(ipv6_sa_addr_mask[3]);                                 \
                        key_field->ext_mask = ipv6_sa_addr_mask;    \
                    }\
                }\
            }\
            arg;\
        }\
        index = CTC_CLI_GET_ARGC_INDEX("ipv6-da");\
        if (0xFF != index) \
        {\
            key_field->type = CTC_FIELD_KEY_IPV6_DA;\
            if(is_add)\
            {\
                CTC_CLI_GET_IPV6_ADDRESS("ip-da", ipv6_da_addr, argv[index + 1]);               \
                ipv6_da_addr[0] = sal_htonl(ipv6_da_addr[0]);                                 \
                ipv6_da_addr[1] = sal_htonl(ipv6_da_addr[1]);                                 \
                ipv6_da_addr[2] = sal_htonl(ipv6_da_addr[2]);                                 \
                ipv6_da_addr[3] = sal_htonl(ipv6_da_addr[3]);                                 \
                key_field->ext_data = ipv6_da_addr;    \
                if(index+2<argc)\
                {\
                    if CLI_CLI_STR_EQUAL("HOST", index + 2)                                          \
                    {                                                                             \
                        ipv6_da_addr_mask[0] = 0xFFFFFFFF;                                            \
                        ipv6_da_addr_mask[1] = 0xFFFFFFFF;                                            \
                        ipv6_da_addr_mask[2] = 0xFFFFFFFF;                                            \
                        ipv6_da_addr_mask[3] = 0xFFFFFFFF;                                            \
                        key_field->ext_mask = ipv6_da_addr_mask;    \
                    }                                                                             \
                    else                                                                          \
                    {                                                                             \
                        CTC_CLI_GET_IPV6_ADDRESS("ip-da-mask", ipv6_da_addr_mask, argv[index + 2]);          \
                        ipv6_da_addr_mask[0] = sal_htonl(ipv6_da_addr_mask[0]);                                 \
                        ipv6_da_addr_mask[1] = sal_htonl(ipv6_da_addr_mask[1]);                                 \
                        ipv6_da_addr_mask[2] = sal_htonl(ipv6_da_addr_mask[2]);                                 \
                        ipv6_da_addr_mask[3] = sal_htonl(ipv6_da_addr_mask[3]);                                 \
                        key_field->ext_mask = ipv6_da_addr_mask;    \
                    } \
                }\
            }\
            arg;\
        }\
        index = CTC_CLI_GET_ARGC_INDEX("ip-protocol");\
        if (0xFF != index) \
        {\
            key_field->type = CTC_FIELD_KEY_IP_PROTOCOL;\
            if(is_add)\
            {\
                CTC_CLI_GET_UINT32("value", key_field->data, argv[index + 1]);\
                if(index+2<argc) CTC_CLI_GET_UINT32("mask", key_field->mask, argv[index + 2]);\
            }\
            arg;\
        }\
        index = CTC_CLI_GET_ARGC_INDEX("ip-frag");\
        if (0xFF != index) \
        {\
            key_field->type = CTC_FIELD_KEY_IP_FRAG;\
            if(is_add)\
            {\
                CTC_CLI_GET_UINT32("value", key_field->data, argv[index + 1]);\
                if(index+2<argc) CTC_CLI_GET_UINT32("mask", key_field->mask, argv[index + 2]);\
            }\
            arg;\
        }\
        index = CTC_CLI_GET_ARGC_INDEX("ip-options");\
        if (0xFF != index) \
        {\
            key_field->type = CTC_FIELD_KEY_IP_OPTIONS;\
            if(is_add)\
            {\
                CTC_CLI_GET_UINT32("value", key_field->data, argv[index + 1]);\
                if(index+2<argc) CTC_CLI_GET_UINT32("mask", key_field->mask, argv[index + 2]);\
            }\
            arg;\
        }\
        index = CTC_CLI_GET_ARGC_INDEX("ip-pkt-len-range");\
        if (0xFF != index) \
        {\
            key_field->type = CTC_FIELD_KEY_IP_PKT_LEN_RANGE;\
            if(is_add)\
            {\
                CTC_CLI_GET_UINT32("value", key_field->data, argv[index + 1]);\
                if(index+2<argc) CTC_CLI_GET_UINT32("mask", key_field->mask, argv[index + 2]);\
            }\
            arg;\
        }\
        index = CTC_CLI_GET_ARGC_INDEX("l4-dst-port");\
        if (0xFF != index) \
        {\
            key_field->type = CTC_FIELD_KEY_L4_DST_PORT;\
            if(is_add)\
            {\
                CTC_CLI_GET_UINT32("value", key_field->data, argv[index + 1]);\
                if(index+2<argc) CTC_CLI_GET_UINT32("mask", key_field->mask, argv[index + 2]);\
            }\
            arg;\
        }\
        index = CTC_CLI_GET_ARGC_INDEX("l4-src-port");\
        if (0xFF != index) \
        {\
            key_field->type = CTC_FIELD_KEY_L4_SRC_PORT;\
            if(is_add)\
            {\
                CTC_CLI_GET_UINT32("value", key_field->data, argv[index + 1]);\
                if(index+2<argc) CTC_CLI_GET_UINT32("mask", key_field->mask, argv[index + 2]);\
            }\
            arg;\
        }\
        index = CTC_CLI_GET_ARGC_INDEX("l4-src-port-range");\
        if (0xFF != index) \
        {\
            key_field->type = CTC_FIELD_KEY_L4_SRC_PORT_RANGE;\
            if(is_add)\
            {\
                CTC_CLI_GET_UINT32("value", key_field->data, argv[index + 1]);\
                if(index+2<argc) CTC_CLI_GET_UINT32("mask", key_field->mask, argv[index + 2]);\
            }\
            arg;\
        }\
        index = CTC_CLI_GET_ARGC_INDEX("l4-dst-port-range");\
        if (0xFF != index) \
        {\
            key_field->type = CTC_FIELD_KEY_L4_DST_PORT_RANGE;\
            if(is_add)\
            {\
                CTC_CLI_GET_UINT32("value", key_field->data, argv[index + 1]);\
                if(index+2<argc) CTC_CLI_GET_UINT32("mask", key_field->mask, argv[index + 2]);\
            }\
            arg;\
        }\
        index = CTC_CLI_GET_ARGC_INDEX("tcp-flags");\
        if (0xFF != index) \
        {\
            key_field->type = CTC_FIELD_KEY_TCP_FLAGS;\
            if(is_add)\
            {\
                CTC_CLI_GET_UINT32("value", key_field->data, argv[index + 1]);\
                if(index+2<argc) CTC_CLI_GET_UINT32("mask", key_field->mask, argv[index + 2]);\
            }\
            arg;\
        }\
        index = CTC_CLI_GET_ARGC_INDEX("icmp-code");\
        if (0xFF != index) \
        {\
            key_field->type = CTC_FIELD_KEY_ICMP_CODE;\
            if(is_add)\
            {\
                CTC_CLI_GET_UINT32("value", key_field->data, argv[index + 1]);\
                if(index+2<argc) CTC_CLI_GET_UINT32("mask", key_field->mask, argv[index + 2]);\
            }\
            arg;\
        }\
        index = CTC_CLI_GET_ARGC_INDEX("icmp-type");\
        if (0xFF != index) \
        {\
            key_field->type = CTC_FIELD_KEY_ICMP_TYPE;\
            if(is_add)\
            {\
                CTC_CLI_GET_UINT32("value", key_field->data, argv[index + 1]);\
                if(index+2<argc) CTC_CLI_GET_UINT32("mask", key_field->mask, argv[index + 2]);\
            }\
            arg;\
        }\
        index = CTC_CLI_GET_ARGC_INDEX("dscp");\
        if (0xFF != index) \
        {\
            key_field->type = CTC_FIELD_KEY_IP_DSCP;\
            if(is_add)\
            {\
                CTC_CLI_GET_UINT32("dscp", key_field->data, argv[index + 1]);\
                if(index+2<argc) CTC_CLI_GET_UINT32("mask", key_field->mask, argv[index + 2]);\
            }\
            arg;\
        }\
        index = ctc_cli_get_prefix_item(&argv[start], (argc - (start)), "udf", 0);\
        if (0xFF != index) \
        {\
            key_field->type = CTC_FIELD_KEY_UDF;\
            index = CTC_CLI_GET_ARGC_INDEX("udf-id");\
            if (INDEX_VALID(index))\
            {\
                CTC_CLI_GET_UINT32("udf-id", udf_data.udf_id, argv[index + 1]);         \
            }\
            if(is_add)\
            {\
                index = CTC_CLI_GET_ARGC_INDEX("udf-data");\
                if (INDEX_VALID(index))\
                {\
                    sal_sscanf(argv[index+1], "%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx", \
                        (uint8*)udf_data.udf,(uint8*)udf_data.udf+1,(uint8*)udf_data.udf+2,(uint8*)udf_data.udf+3,(uint8*)udf_data.udf+4,(uint8*)udf_data.udf+5,(uint8*)udf_data.udf+6,(uint8*)udf_data.udf+7, \
                        (uint8*)udf_data.udf+8,(uint8*)udf_data.udf+9,(uint8*)udf_data.udf+10,(uint8*)udf_data.udf+11,(uint8*)udf_data.udf+12,(uint8*)udf_data.udf+13,(uint8*)udf_data.udf+14,(uint8*)udf_data.udf+15);\
                    sal_sscanf(argv[index+2], "%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx",\
                        (uint8*)udf_data_mask.udf,(uint8*)udf_data_mask.udf+1,(uint8*)udf_data_mask.udf+2,(uint8*)udf_data_mask.udf+3,(uint8*)udf_data_mask.udf+4,(uint8*)udf_data_mask.udf+5,(uint8*)udf_data_mask.udf+6,(uint8*)udf_data_mask.udf+7, \
                        (uint8*)udf_data_mask.udf+8,(uint8*)udf_data_mask.udf+9,(uint8*)udf_data_mask.udf+10,(uint8*)udf_data_mask.udf+11,(uint8*)udf_data_mask.udf+12,(uint8*)udf_data_mask.udf+13,(uint8*)udf_data_mask.udf+14,(uint8*)udf_data_mask.udf+15);\
                }\
                key_field->ext_data = &udf_data;\
                key_field->ext_mask = &udf_data_mask;\
            }\
            arg;\
        }\
        index = CTC_CLI_GET_ARGC_INDEX("field-port");\
        if(0xFF != index)\
        {\
            key_field->type = CTC_FIELD_KEY_PORT;\
            index = CTC_CLI_GET_ARGC_INDEX("port-bitmap");\
            if(INDEX_VALID(index))\
            {\
                port_info.type = CTC_FIELD_PORT_TYPE_PORT_BITMAP;\
                if(is_add)\
                {\
                    CTC_CLI_GET_UINT32("port-bitmap", port_info.port_bitmap[0], argv[index + 1]);\
                    if(index+2<argc){ CTC_CLI_GET_UINT32("mask", port_info_mask.port_bitmap[0], argv[index + 2]);\
                    key_field->ext_mask = &port_info_mask; }\
                }\
                key_field->ext_data = &port_info;\
                arg;\
            }\
        }\
        index = CTC_CLI_GET_ARGC_INDEX("valid");\
        if (0xFF != index) \
        {\
            key_field->type = CTC_FIELD_KEY_UDF_ENTRY_VALID;\
            if(is_add)\
            {\
                CTC_CLI_GET_UINT32("value", key_field->data, argv[index + 1]);\
                if(index+2<argc) CTC_CLI_GET_UINT32("mask", key_field->mask, argv[index + 2]);\
            }\
            arg;\
        }\
    }while(0)


#define CTC_CLI_ACL_UDF_KEY_FIELD_STR \
    " l2-type (eth-v2 | eth-sap | eth-snap | ) (MASK|) \
    | l4-type (tcp | udp | icmp | igmp |) (MASK|) \
    | stag-valid (VALUE (MASK|)|) \
    | ctag-valid (VALUE (MASK|)|) \
    | field-port (port-bitmap PORT_BITMAP) \
    | ether-type (VALUE (MASK|)|) \
    | ip-protocol (VALUE (MASK|)|) \
    | ip-frag (VALUE (MASK|)|) \
    | ip-options (VALUE (MASK|)|) \
    | l4-dst-port (VALUE (MASK|)|) \
    | l4-src-port (VALUE (MASK|)|) \
    | valid (VALUE (MASK|)|) \
    "

#define CTC_CLI_ACL_UDF_KEY_FIELD_DESC \
    "layer 2 type  ", "eth-v2", "eth-sap", "eth-snap", "mask",\
    "layer 4 type", "tcp" , "udp" , "icmp" , "igmp","mask",\
    "s-vlan exist ", "value", "mask",\
    "c-vlan exist ", "value", "mask",\
    "port-type", "Port bitmap","port bitmap <port0~port27>",\
    "ether type ", "value", "mask",\
    "ip protocol ", "value", "mask",\
    "ip fragment information ", "value", "mask",\
    "ip options ", "value", "mask",\
    "layer 4 dest port ", "value", "mask",\
    "layer 4 src port ", "value", "mask", \
    "UDF Entry valid ", "value", "mask"

#define CTC_CLI_ACL_ADD_ENTRY_DESC  \
    "ACL module ", \
    "Add one entry to hardware table",\
    "ACL entry id",\
    "ACL entry id value"

#define CTC_CLI_ACL_ADD_FIELD_DESC  \
    "ACL module ", \
    "ACL entry id",\
    "ACL entry id value"


#define CTC_CLI_ACL_COMMON_VAR \
    mac_addr_t  mac_da_addr = {0};\
    mac_addr_t  mac_da_addr_mask = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};\
    mac_addr_t  mac_sa_addr = {0};\
    mac_addr_t  mac_sa_addr_mask = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};\
    ipv6_addr_t ipv6_da_addr = {0};\
    ipv6_addr_t ipv6_da_addr_mask = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF};\
    ipv6_addr_t ipv6_sa_addr = {0};\
    ipv6_addr_t ipv6_sa_addr_mask = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF};


CTC_CLI(ctc_cli_asw_acl_add_entry,
        ctc_cli_asw_acl_add_entry_cmd,
        "acl add entry ENTRY_ID (" CTC_CLI_ACL_ENTRY_TYPE_STR ")",
        CTC_CLI_ACL_ADD_ENTRY_DESC,
        CTC_CLI_ACL_ENTRY_TYPE_DESC)
{
    int32 ret = CLI_SUCCESS;
    uint8 index = 0xFF;
    ctc_acl_entry_t acl_entry;

    sal_memset(&acl_entry, 0, sizeof(ctc_acl_entry_t));

    CTC_CLI_GET_UINT32("entry-id", acl_entry.entry_id, argv[0]);
    CTC_CLI_ACL_KEY_TYPE_SET;

     ret = ctcs_acl_add_entry(g_api_lchip, 0, &acl_entry);

    if (ret < 0)
    {
        ctc_cli_out("%% ret =%d\n", ret);
        return CLI_ERROR;
    }
    return ret;
}


CTC_CLI(ctc_cli_asw_acl_remove_entry,
        ctc_cli_asw_acl_remove_entry_cmd,
        "acl remove entry ENTRY_ID",
        CTC_CLI_ACL_STR,
        "Remove one entry from software table",
        CTC_CLI_ACL_ENTRY_ID_STR,
        CTC_CLI_ACL_ENTRY_ID_VALUE)
{

    int32 ret = CLI_SUCCESS;
    uint32 eid = 0;

    CTC_CLI_GET_UINT32("entry id", eid, argv[0]);

    ret = ctcs_acl_remove_entry(g_api_lchip, eid);

    if (ret < 0)
    {
        ctc_cli_out("%% ret =%d.\n", ret);
        return CLI_ERROR;
    }

    return ret;
}


CTC_CLI(ctc_cli_asw_acl_add_key_field,
        ctc_cli_asw_acl_add_key_field_cmd,
        "acl entry ENTRY_ID (add|remove) key-field {"CTC_CLI_ACL_KEY_FIELD_STR "}",
        CTC_CLI_ACL_ADD_FIELD_DESC,
        "add",
        "remove",
        "key field",
        CTC_CLI_ACL_KEY_FIELD_DESC)
{
    int32 ret = CLI_SUCCESS;
    uint8 index = 0xFF;
    uint32 field_cnt = 0;
    uint8 is_add = 0;
    ctc_field_port_t port_info;
    ctc_field_port_t port_info_mask;
    ctc_field_key_t key_field[CTC_CLI_ACL_KEY_FIELED_GREP_NUM];
    ctc_field_key_t* p_field = &key_field[0];
    uint32 entry_id;
    ctc_acl_udf_t udf_data;
    ctc_acl_udf_t udf_data_mask;
    CTC_CLI_ACL_COMMON_VAR;

    sal_memset(&port_info, 0, sizeof(ctc_field_port_t));
    sal_memset(&port_info_mask, 0xFF, sizeof(ctc_field_port_t));
    sal_memset(&udf_data, 0, sizeof(ctc_acl_udf_t));
    sal_memset(&udf_data_mask, 0xFF, sizeof(ctc_acl_udf_t));
    sal_memset(key_field, 0, sizeof(ctc_field_key_t));

    CTC_CLI_GET_UINT32("entry-id", entry_id, argv[0]);
    index = CTC_CLI_GET_ARGC_INDEX("add");
    if (0xFF != index)
    {
        is_add = 1;
    }

    CTC_CLI_ACL_KEY_FIELD_SET(p_field,CTC_CLI_ACL_KEY_ARG_CHECK(field_cnt,CTC_CLI_ACL_KEY_FIELED_GREP_NUM, p_field), 0);

    if (is_add)
    {
        ret = ctcs_acl_add_key_field_list(g_api_lchip, entry_id, key_field, &field_cnt);
    }
    else
    {
        /*ret = ctcs_acl_remove_key_field_list(g_api_lchip, &acl_entry);*/
    }

    if (ret < 0)
    {
        ctc_cli_out("%% ret =%d\n", ret);
        return CLI_ERROR;
    }
    return ret;
}


CTC_CLI(ctc_cli_asw_acl_add_action_field,
        ctc_cli_asw_acl_add_action_field_cmd,
        "acl entry ENTRY_ID (add | remove) action-field {" CTC_CLI_ACL_ADD_FIELD_ACTION_STR "}",
        CTC_CLI_ACL_STR,
        "Acl entry id",
        "ENTRY_ID",
        "Add one action field to an entry",
        "Remove one action field to an entry",
        "Action field",
        CTC_CLI_ACL_ADD_FIELD_ACTION_DESC)
{
    int32 ret = CLI_SUCCESS;
    uint8 index = 0;
    uint32 entry_id = 0;
    uint32 arg_cnt = 0;
    ctc_acl_field_action_t act_field[CTC_CLI_ACL_KEY_FIELED_GREP_NUM];
    ctc_acl_field_action_t* p_field = &act_field[0];
    uint8 is_add = 0;
    ctc_acl_vlan_edit_t vlan_edit;
    ctc_acl_table_map_t qos_map;
    ctc_acl_to_cpu_t cp_to_cpu;

    sal_memset(act_field, 0, CTC_CLI_ACL_KEY_FIELED_GREP_NUM *sizeof(ctc_acl_field_action_t));
    sal_memset(&cp_to_cpu, 0, sizeof(ctc_acl_to_cpu_t));
    sal_memset(&qos_map, 0, sizeof(ctc_acl_table_map_t));
    sal_memset(&vlan_edit, 0, sizeof(ctc_acl_vlan_edit_t));

    CTC_CLI_GET_UINT32("entry-id", entry_id, argv[0]);
	index = CTC_CLI_GET_ARGC_INDEX("add");
    if (0xFF != index)
    {
        is_add = 1;
    }
    CTC_CLI_ACL_ADD_FIELD_ACTION_SET(p_field,CTC_CLI_ACL_KEY_ARG_CHECK(arg_cnt,CTC_CLI_ACL_KEY_FIELED_GREP_NUM,p_field));

    if (is_add)
    {
        ret = ctcs_acl_add_action_field_list(g_api_lchip, entry_id, act_field, &arg_cnt);
    }
    else
    {
        ret = ctcs_acl_remove_action_field_list(g_api_lchip, entry_id, act_field, &arg_cnt);
    }
    if (ret < 0)
    {
        ctc_cli_out("%% ret =%d.\n", ret);
        if (1 < arg_cnt)
        {
            ctc_cli_out("%% add %u field successfully! \n", arg_cnt);
        }
        return CLI_ERROR;
    }

    return ret;
}


CTC_CLI(ctc_cli_asw_acl_install_entry,
        ctc_cli_asw_acl_install_entry_cmd,
        "acl install entry ENTRY_ID",
        CTC_CLI_ACL_STR,
        "Install to hardware",
        CTC_CLI_ACL_ENTRY_ID_STR,
        CTC_CLI_ACL_ENTRY_ID_VALUE)
{
    int32 ret = CLI_SUCCESS;
    uint32 eid = 0;

    CTC_CLI_GET_UINT32("entry id", eid, argv[0]);

    ret = ctcs_acl_install_entry(g_api_lchip, eid);

    if (ret < 0)
    {
        ctc_cli_out("%% ret =%d.\n", ret);
        return CLI_ERROR;
    }

    return ret;
}

CTC_CLI(ctc_cli_asw_acl_uninstall_entry,
        ctc_cli_asw_acl_uninstall_entry_cmd,
        "acl uninstall entry ENTRY_ID",
        CTC_CLI_ACL_STR,
        "Uninstall from hardware",
        CTC_CLI_ACL_ENTRY_ID_STR,
        CTC_CLI_ACL_ENTRY_ID_VALUE)
{

    int32 ret = CLI_SUCCESS;
    uint32 eid = 0;

    CTC_CLI_GET_UINT32("entry id", eid, argv[0]);

    ret = ctcs_acl_uninstall_entry(g_api_lchip, eid);

    if (ret < 0)
    {
        ctc_cli_out("%% ret =%d.\n", ret);
        return CLI_ERROR;
    }

    return ret;
}


CTC_CLI(ctc_cli_asw_acl_add_udf_entry,
        ctc_cli_asw_acl_add_udf_entry_cmd,
        "acl add udf-entry UDF-ID  {offset0-type  TYPE| offset1-type  TYPE| offset2-type  TYPE |offset3-type  TYPE } \
        {offset0  OFFSET |offset1  OFFSET |offset2  OFFSET |offset3  OFFSET } ",
        CTC_CLI_ACL_STR,
        "Add",
        "UDF Entry",
        "UDF ID",
        "Start offset0-type","TYPE, refer to ctc_acl_udf_offset_type_t",
        "Start offset1-type","TYPE, refer to ctc_acl_udf_offset_type_t",
        "Start offset2-type","TYPE, refer to ctc_acl_udf_offset_type_t",
        "Start offset3-type","TYPE, refer to ctc_acl_udf_offset_type_t",
        "Offset0", "Offset Value",
        "Offset1", "Offset Value",
        "Offset2", "Offset Value",
        "Offset3", "Offset Value")
{
    int32 ret = CLI_SUCCESS;
    uint8 index = 0;
    uint8 loop = 0;
    ctc_acl_classify_udf_t udf_entry;
    char* offset_type_array_str[] = { "offset0-type",  "offset1-type",  "offset2-type",  "offset3-type"};
    char* offset_array_str[] = { "offset0",  "offset1",  "offset2",  "offset3"};

    sal_memset(&udf_entry,0,sizeof(ctc_acl_classify_udf_t));

    udf_entry.offset_num = 0;
    CTC_CLI_GET_UINT32("udf-id", udf_entry.udf_id, argv[0]);
    for (loop=0; loop<CTC_ASW_ACL_UDF_FIELD_NUM; loop++)
    {
        index = CTC_CLI_GET_ARGC_INDEX(offset_type_array_str[loop]);
        if (0xFF != index)
        {
            CTC_CLI_GET_UINT8(offset_type_array_str[loop], udf_entry.offset_type_array[loop], argv[index + 1]);
        }
        index = CTC_CLI_GET_ARGC_INDEX(offset_array_str[loop]);
        if (0xFF != index)
        {
            CTC_CLI_GET_UINT8(offset_array_str[loop], udf_entry.offset[loop], argv[index + 1]);
            udf_entry.offset_num++;
        }
    }

    ret = ctcs_acl_add_udf_entry(g_api_lchip, &udf_entry);
    if (ret < 0)
    {
        ctc_cli_out("%% ret =%d\n", ret);
        return CLI_ERROR;
    }

    return ret;
}


CTC_CLI(ctc_cli_asw_acl_remove_udf_entry,
        ctc_cli_asw_acl_remove_udf_entry_cmd,
        "acl remove udf-entry UDF-ID",
        CTC_CLI_ACL_STR,
        "Remove",
        "UDF Entry",
        "UDF ID")
{
    int32 ret = CLI_SUCCESS;
    ctc_acl_classify_udf_t udf_entry;
    sal_memset(&udf_entry, 0, sizeof(ctc_acl_classify_udf_t));

    CTC_CLI_GET_UINT32("udf-id", udf_entry.udf_id, argv[0]);

    ret = ctcs_acl_remove_udf_entry(g_api_lchip, &udf_entry);

    if (ret < 0)
    {
        ctc_cli_out("%% ret =%d\n", ret);
        return CLI_ERROR;
    }


    return ret;
}

CTC_CLI(ctc_cli_asw_acl_add_remove_udf_entry_key_field,
        ctc_cli_asw_acl_add_remove_udf_entry_key_field_cmd,
        "acl udf-entry UDF_ID (add|remove) key-field{" CTC_CLI_ACL_UDF_KEY_FIELD_STR"}",
        CTC_CLI_ACL_STR,
        "UDF Entry",
        "UDF entry id",
        "Add udf entry",
        "Remove udf entry",
        "key field",
        CTC_CLI_ACL_UDF_KEY_FIELD_DESC)
{
    int32 ret = CLI_SUCCESS;
    uint8 index = 0;
    uint8 field_cnt = 0;
    uint8 is_add = 0;
    uint32 entry_id = 0;
    ctc_field_port_t port_info;
    ctc_field_port_t port_info_mask;
    ctc_field_key_t key_field[8];
    ctc_field_key_t* p_field = NULL;
    ctc_acl_udf_t udf_data;
    ctc_acl_udf_t udf_data_mask;
    CTC_CLI_ACL_COMMON_VAR;

    sal_memset(&port_info, 0, sizeof(ctc_field_port_t));
    sal_memset(&port_info_mask, 0, sizeof(ctc_field_port_t));
    sal_memset(key_field, 0, sizeof(key_field));
    p_field = key_field;

    CTC_CLI_GET_UINT32("entry-id", entry_id, argv[0]);

    index = CTC_CLI_GET_ARGC_INDEX("add");
    if (0xFF != index)
    {
        is_add = 1;
    }

    CTC_CLI_ACL_KEY_FIELD_SET(p_field, CTC_CLI_ACL_KEY_ARG_CHECK(field_cnt,8, p_field), 3);


    for(index = 0; index<field_cnt; index++)
    {
        if(is_add)
        {
            ret = ctcs_acl_add_udf_entry_key_field(g_api_lchip, entry_id, &key_field[index]);
        }
        else
        {
            /*ret = ctcs_acl_remove_udf_entry_key_field_list(g_api_lchip, entry_id, &key_field);*/
        }
    }

    if (ret < 0)
    {
        ctc_cli_out("%% ret =%d\n", ret);
        return CLI_ERROR;
    }

    return ret;
}


CTC_CLI(ctc_cli_asw_acl_add_range_info,
        ctc_cli_asw_acl_add_range_info_cmd,
        "acl add range-info index INDEX range-type (ip-pkt-len| l4-sport | l4-dport) min MIN max MAX",
        CTC_CLI_ACL_STR,
        "Add",
        "Range info",
        "Range id",
        "Index value",
        "Range type",
        "Ip packet length",
        "L4 source port",
        "L4 dest port",
        "Min",
        "Min value",
        "Max",
        "Max value")
{
    int32 ret = CLI_SUCCESS;
    uint32 range_id = 0;
    ctc_acl_range_t range_info = {0};
    uint8 index = 0xff;

    CTC_CLI_GET_UINT32("range_id", range_id, argv[0]);
    index = CTC_CLI_GET_ARGC_INDEX("ip-pkt-len");
    if(index != 0xff)
    {
        range_info.type = CTC_ACL_RANGE_TYPE_PKT_LENGTH;
    }
    index = CTC_CLI_GET_ARGC_INDEX("l4-sport");
    if(index != 0xff)
    {
        range_info.type = CTC_ACL_RANGE_TYPE_L4_SRC_PORT;
    }
    index = CTC_CLI_GET_ARGC_INDEX("l4-dport");
    if(index != 0xff)
    {
        range_info.type = CTC_ACL_RANGE_TYPE_L4_DST_PORT;
    }

    CTC_CLI_GET_UINT32("range_min", range_info.min, argv[2]);
    CTC_CLI_GET_UINT32("range_max", range_info.max, argv[3]);

    ret = ctcs_acl_add_range_info(g_api_lchip, &range_info, range_id);

    if (ret < 0)
    {
        ctc_cli_out("%% ret =%d\n", ret);
        return CLI_ERROR;
    }

    return ret;
}

CTC_CLI(ctc_cli_asw_acl_remove_range_info,
        ctc_cli_asw_acl_remove_range_info_cmd,
        "acl remove range-info index INDEX ",
        CTC_CLI_ACL_STR,
        "Remove",
        "Range info",
        "Range id",
        "Range indx value")
{
    int32 ret = CLI_SUCCESS;
    uint32 range_id = 0;

    CTC_CLI_GET_UINT32("range_id", range_id, argv[0]);

    ret = ctcs_acl_remove_range_info(g_api_lchip, range_id);

    if (ret < 0)
    {
        ctc_cli_out("%% ret =%d\n", ret);
        return CLI_ERROR;
    }

    return ret;
}


CTC_CLI(ctc_cli_asw_acl_entry_all,
        ctc_cli_asw_acl_entry_all_cmd,
        "show acl entry all",
        "Show",
        "Acl",
        "Acl entry",
        "All")
{
    uint8 is_hw = 1;
    uint8 lchip = g_api_lchip;
    uint32 num = 0;
    uint32 total_num = 0;
    int32 ret = CLI_SUCCESS;
    char* type_new[] = {"Tcam-Mac","Tcam-Mac-Ext", "Tcam-Ipv4","Tcam-Mac-Ipv4", "Tcam-Ipv4-Ext","Tcam-Mac-Ipv6", "Tcam-Ipv6", "Tcam-Ipv6-Ext","Tcam-Udf"};
    char* type_tbl_id[] = {"Key160MacView0", "Key160MacudfView0", "Key160IpView0", "Key320MacipudfView0", "Key320IpudfView0","Key640Macipv6View0", "Key320Ipv6View0", "Key640Macipv6udfView0", "Key160EthudfView0"};
    char* action_new[] = {"Forward","Discard"};
    
    acl_entry_para_t * p_acl_entry_para;

    p_acl_entry_para = (acl_entry_para_t*)mem_malloc(MEM_CLI_MODULE, sizeof(acl_entry_para_t)*MAX_ACL_ENTRY_REG_NUM);
    if (NULL == p_acl_entry_para)
    {
        return CLI_ERROR;
    }
    ctc_cli_out("%-8s%-12s%-4s%-15s%-25s%-8s%-10s%s\n", "No.", "ENTRY_ID", "HW", "TYPE", "TABLE", "INDEX","ACTION", "SIZE");
    ctc_cli_out("----------------------------------------------------------------------------------------\n");


    ret = ctc_cli_asw_acl_get_entry_all(vty, lchip,p_acl_entry_para,&total_num);

    while (num < total_num)
    {
        ctc_cli_out("%-8d%-12d%-4d%-15s%-25s%-8d%-10s%d\n", num, p_acl_entry_para[num].table_index, is_hw, type_new[p_acl_entry_para[num].key_type], type_tbl_id[p_acl_entry_para[num].key_type],
                     p_acl_entry_para[num].table_index, action_new[p_acl_entry_para[num].action_type], p_acl_entry_para[num].size);
        num ++;
    }
    ctc_cli_out("----------------------------------------------------------------------------------------\n");
    ctc_cli_out("%-18s\n", "Total Entry Num:128");
    ctc_cli_out("%-18s%d\n", "Used Entry Num:",num);

    mem_free(p_acl_entry_para);
    return ret;
}

int32
ctc_asw_acl_cli_init(uint8 cli_tree_mode)
{
    install_element(cli_tree_mode, &ctc_cli_asw_acl_add_entry_cmd);
    install_element(cli_tree_mode, &ctc_cli_asw_acl_remove_entry_cmd);
    install_element(cli_tree_mode, &ctc_cli_asw_acl_add_key_field_cmd);
    install_element(cli_tree_mode, &ctc_cli_asw_acl_add_action_field_cmd);
    install_element(cli_tree_mode, &ctc_cli_asw_acl_install_entry_cmd);
    install_element(cli_tree_mode, &ctc_cli_asw_acl_uninstall_entry_cmd);
    install_element(cli_tree_mode, &ctc_cli_asw_acl_add_range_info_cmd);
    install_element(cli_tree_mode, &ctc_cli_asw_acl_remove_range_info_cmd);
    install_element(cli_tree_mode, &ctc_cli_asw_acl_add_udf_entry_cmd);
    install_element(cli_tree_mode, &ctc_cli_asw_acl_remove_udf_entry_cmd);
    install_element(cli_tree_mode, &ctc_cli_asw_acl_add_remove_udf_entry_key_field_cmd);
    install_element(cli_tree_mode, &ctc_cli_asw_acl_entry_all_cmd);
    return 0;
}


